import json
from typing import Dict, Any, List, Optional, Union

from sqlalchemy.orm import Session

from config.logging_config import get_logger
from mcp_tools.mcpClient import mcp_client
from mcp_tools.mcpManager import mcp_manager
from pojo.ai_web_mcp_tools_model import AIWebMCPToolsModel

logger = get_logger(__name__)


class MCPFactory:
    """MCP工厂类 - 基于mcpClient的增强版本"""

    # 预定义的MCP配置模板
    _mcp_templates = {
    }

    @classmethod
    async def create_mcp_connection(cls, mcp_id: str, mcp_name: str, config: Dict[str, Any]) -> bool:
        """创建MCP连接，替代原来的create_mcp_interface"""
        try:
            # 使用mcp_client连接服务器
            success = await mcp_client.connect_from_json_schema(mcp_name, config)

            if success:
                logger.info(f"MCP连接创建成功: {mcp_name}")
            else:
                logger.error(f"MCP连接创建失败: {mcp_name}")

            return success
        except Exception as e:
            logger.error(f"创建MCP连接失败 {mcp_name}: {str(e)}")
            return False

    @classmethod
    async def create_mcps_from_list(cls, mcp_list: List[Union[str, Dict[str, Any]]], db: Session = None) -> List[str]:
        """从MCP列表创建连接，返回成功连接的服务器名称列表"""
        connected_servers = []

        if not mcp_list:
            return connected_servers

        try:
            mcp_ids = mcp_list
            # 处理MCP ID列表（需要数据库查询）
            if mcp_ids and db is not None:
                # 查询指定的MCP工具
                mcp_tools = db.query(AIWebMCPToolsModel).filter(
                    AIWebMCPToolsModel.id.in_(mcp_ids),
                    AIWebMCPToolsModel.status == 1  # 只获取已上线的
                ).all()

                for mcp_tool in mcp_tools:
                    if mcp_tool.json_schema:
                        success = await cls.create_mcp_connection(
                            mcp_id=str(mcp_tool.id),
                            mcp_name=mcp_tool.mcp_name,
                            config=mcp_tool.json_schema
                        )
                        if success:
                            connected_servers.append(mcp_tool.mcp_name)
            elif mcp_ids and db is None:
                logger.warning(f"无法从ID {mcp_ids} 创建MCP连接: 未提供数据库会话")

            logger.info(f"总共创建了 {len(connected_servers)} 个MCP连接")
            return connected_servers

        except Exception as e:
            logger.error(f"从列表创建MCP连接失败: {str(e)}")
            return []

    @classmethod
    async def create_mcps_from_ids(cls, db: Session, mcp_ids: List[str]) -> List[str]:
        """从MCP ID列表创建连接"""
        connected_servers = []

        if not mcp_ids:
            return connected_servers

        try:
            from pojo.ai_web_mcp_tools_model import AIWebMCPToolsModel

            # 查询指定的MCP工具
            mcp_tools = db.query(AIWebMCPToolsModel).filter(
                AIWebMCPToolsModel.id.in_(mcp_ids),
                AIWebMCPToolsModel.status == 1  # 只获取已上线的
            ).all()

            for mcp_tool in mcp_tools:
                if mcp_tool.json_schema:
                    success = await cls.create_mcp_connection(
                        mcp_id=str(mcp_tool.id),
                        mcp_name=mcp_tool.mcp_name,
                        config=mcp_tool.json_schema
                    )
                    if success:
                        connected_servers.append(mcp_tool.mcp_name)
                        logger.info(f"从ID创建MCP连接: {mcp_tool.mcp_name}")

            logger.info(f"从ID列表创建了 {len(connected_servers)} 个MCP连接")
            return connected_servers

        except Exception as e:
            logger.error(f"从ID创建MCP连接失败: {str(e)}")
            return []

    @classmethod
    def get_available_types(cls) -> Dict[str, str]:
        """获取可用的MCP类型"""
        return {
            "stdio": "标准输入输出传输",
            "streamable_http": "可流式HTTP传输",
            "sse": "服务器发送事件传输",
            "websocket": "WebSocket传输"
        }

    @classmethod
    def get_available_templates(cls) -> Dict[str, Dict[str, Any]]:
        """获取可用的MCP模板"""
        return cls._mcp_templates.copy()

    @classmethod
    def create_from_template(cls, template_name: str, custom_config: Dict[str, Any] = None) -> Optional[Dict[str, Any]]:
        """根据模板创建MCP配置"""
        template = cls._mcp_templates.get(template_name)
        if not template:
            logger.error(f"Template not found: {template_name}")
            return None

        config = template.copy()
        if custom_config:
            config.update(custom_config)

        return config

    @classmethod
    def register_mcp_template(cls, template_name: str, config: Dict[str, Any]):
        """注册新的MCP模板"""
        cls._mcp_templates[template_name] = config
        logger.info(f"Registered MCP template: {template_name}")

    @classmethod
    def validate_mcp_config(cls, config: Dict[str, Any]) -> tuple[bool, List[str]]:
        """验证MCP配置"""
        errors = []

        # 检查传输类型
        transport = config.get("transport")
        if not transport:
            errors.append("Missing transport type")
        elif transport not in ["stdio", "streamable_http", "sse", "websocket"]:
            errors.append(f"Invalid transport type: {transport}")

        # 根据传输类型检查相应字段
        if transport == "stdio":
            if not config.get("command"):
                errors.append("stdio transport requires command field")
        elif transport in ["streamable_http", "sse", "websocket"]:
            url = config.get("url") or config.get("endpoint")
            if not url:
                errors.append(f"{transport} transport requires url or endpoint field")
            elif not (url.startswith("http://") or url.startswith("https://") or url.startswith(
                    "ws://") or url.startswith("wss://")):
                errors.append("URL must be a valid HTTP/HTTPS/WS/WSS URL")

        return len(errors) == 0, errors

    @classmethod
    async def test_mcp_connections(cls, db: Session) -> Dict[str, bool]:
        """测试MCP连接"""
        try:
            connected_servers = mcp_client.get_connected_servers()
            results = {}

            for server_name in connected_servers:
                try:
                    success = await mcp_client.test_connection(server_name)
                    results[server_name] = success
                except Exception as e:
                    logger.error(f"测试连接失败 {server_name}: {str(e)}")
                    results[server_name] = False

            logger.info(f"连接测试完成: {sum(results.values())}/{len(results)} 个连接正常")
            return results

        except Exception as e:
            logger.error(f"测试MCP连接失败: {str(e)}")
            return {}

    @classmethod
    async def get_mcp_tools_for_langchain(cls, db: Session, mcp_ids: List[str] = None) -> List[Dict[str, Any]]:
        """获取MCP工具供LangChain使用"""
        try:
            tools = await mcp_client.get_tools()

            tool_list = []
            for tool in tools:
                tool_dict = {
                    "name": tool.name,
                    "description": tool.description,
                    "input_schema": tool.input_schema,
                    "server_name": tool.server_name
                }
                tool_list.append(tool_dict)

            logger.info(f"获取到 {len(tool_list)} 个MCP工具供LangChain使用")
            return tool_list

        except Exception as e:
            logger.error(f"获取MCP工具失败: {str(e)}")
            return []

    @classmethod
    async def create_langchain_tools(cls, db: Session, mcp_ids: List[str] = None) -> List[Any]:
        """创建LangChain工具对象"""
        try:
            return await mcp_client.get_langchain_tools()
        except Exception as e:
            logger.error(f"创建LangChain工具失败: {str(e)}")
            return []

    @classmethod
    def get_mcp_statistics(cls, db: Session) -> Dict[str, Any]:
        """获取MCP统计信息"""
        try:
            connected_servers = mcp_client.get_connected_servers()

            stats = {
                "connected_servers_count": len(connected_servers),
                "connected_servers": connected_servers,
                "available_tools_count": len(mcp_client.available_tools),
                "available_tools": list(mcp_client.available_tools.keys())
            }

            logger.info(f"MCP统计: {stats}")
            return stats

        except Exception as e:
            logger.error(f"获取MCP统计失败: {str(e)}")
            return {
                "connected_servers_count": 0,
                "connected_servers": [],
                "available_tools_count": 0,
                "available_tools": []
            }

    @classmethod
    def export_mcp_config(cls, db: Session, mcp_id: str) -> Optional[Dict[str, Any]]:
        """导出MCP配置"""
        try:
            from pojo.ai_web_mcp_tools_model import AIWebMCPToolsModel

            mcp_tool = db.query(AIWebMCPToolsModel).filter(
                AIWebMCPToolsModel.id == mcp_id
            ).first()

            if not mcp_tool:
                return None

            # 获取相关工具
            tools = mcp_manager.get_mcp_tools_from_database(db, mcp_id)

            config = {
                "mcp_name": mcp_tool.mcp_name,
                "description": mcp_tool.description,
                "status": mcp_tool.status,
                "access_type": mcp_tool.access_type,
                "doc_url": mcp_tool.doc_url,
                "json_schema": mcp_tool.json_schema,
                "tools": tools,
                "export_time": str(mcp_tool.created_at),
                "tools_count": len(tools)
            }

            return config

        except Exception as e:
            logger.error(f"Error exporting MCP config: {str(e)}")
            return None

    @classmethod
    def get_enabled_mcps(cls, db: Session) -> List[str]:
        """从数据库获取启用的MCP工具ID列表"""
        try:
            from pojo.ai_web_mcp_tools_model import AIWebMCPToolsModel

            # 查询所有已上线的MCP工具
            enabled_mcps = db.query(AIWebMCPToolsModel).filter(
                AIWebMCPToolsModel.status == 1  # 已上线
            ).all()

            mcp_ids = [str(mcp.id) for mcp in enabled_mcps]
            logger.info(f"找到 {len(mcp_ids)} 个启用的MCP工具")

            return mcp_ids

        except Exception as e:
            logger.error(f"获取启用MCP工具失败: {str(e)}")
            return []

    @classmethod
    def get_enabled_mcp_details(cls, db: Session) -> List[Dict[str, Any]]:
        """获取启用的MCP工具详细信息"""
        try:
            from pojo.ai_web_mcp_tools_model import AIWebMCPToolsModel

            # 查询所有已上线的MCP工具
            enabled_mcps = db.query(AIWebMCPToolsModel).filter(
                AIWebMCPToolsModel.status == 1  # 已上线
            ).all()

            mcp_details = []
            for mcp in enabled_mcps:
                detail = {
                    "id": mcp.id,
                    "mcp_name": mcp.mcp_name,
                    "description": mcp.description,
                    "access_type": mcp.access_type,
                    "json_schema": mcp.json_schema,
                    "doc_url": mcp.doc_url,
                    "status": mcp.status,
                    "created_at": str(mcp.created_at),
                    "updated_at": str(mcp.updated_at)
                }
                mcp_details.append(detail)

            logger.info(f"获取到 {len(mcp_details)} 个启用的MCP工具详情")
            return mcp_details

        except Exception as e:
            logger.error(f"获取启用MCP工具详情失败: {str(e)}")
            return []

    @classmethod
    def validate_mcp_configuration(cls, mcp_id: str, db: Session) -> bool:
        """验证MCP配置是否正确"""
        try:
            from pojo.ai_web_mcp_tools_model import AIWebMCPToolsModel

            # 查找MCP工具
            mcp_tool = db.query(AIWebMCPToolsModel).filter(
                AIWebMCPToolsModel.id == mcp_id
            ).first()

            if not mcp_tool:
                logger.error(f"MCP工具 {mcp_id} 不存在")
                return False

            # 检查必要的配置
            if not mcp_tool.mcp_name:
                logger.error(f"MCP工具 {mcp_id} 缺少名称")
                return False

            if not mcp_tool.json_schema:
                logger.error(f"MCP工具 {mcp_id} 缺少JSON配置")
                return False

            # 验证JSON配置
            is_valid, errors = cls.validate_mcp_config(mcp_tool.json_schema)
            if not is_valid:
                logger.error(f"MCP工具 {mcp_id} 配置错误: {', '.join(errors)}")
                return False

            logger.info(f"MCP工具配置验证通过: {mcp_id} - {mcp_tool.mcp_name}")
            return True

        except Exception as e:
            logger.error(f"验证MCP配置失败: {str(e)}")
            return False

    @classmethod
    async def call_mcp_tool(cls, mcp_service: Optional[str], tool_name: str, parameters: str = "{}") -> str:
        """调用MCP工具，使用mcp_client"""
        try:
            logger.info(f"🔧 开始调用MCP工具: {mcp_service}.{tool_name}")

            # 解析参数
            try:
                tool_params = json.loads(parameters) if parameters else {}
            except json.JSONDecodeError as e:
                error_msg = f"参数格式错误，必须是有效的JSON字符串: {str(e)}"
                logger.error(error_msg)
                return f"❌ 调用失败: {error_msg}"

            # 使用mcp_client调用工具
            logger.info(f"📡 调用MCP工具: {mcp_service}.{tool_name}，参数: {tool_params}")
            result = await mcp_client.call_tool(mcp_service, tool_name, tool_params)

            # 处理结果
            if result.get("success"):
                result_str = json.dumps(result.get("result", {}), ensure_ascii=False, indent=2)
                success_msg = f"✅ MCP工具调用成功\n服务: {mcp_service}\n工具: {tool_name}\n结果: {result_str}"
                logger.info(f"✅ MCP工具调用成功: {mcp_service}.{tool_name}")
                return success_msg
            else:
                error_msg = result.get("error", "未知错误")
                logger.error(f"❌ MCP工具调用失败: {error_msg}")
                return f"❌ 调用失败: {error_msg}"

        except Exception as e:
            error_msg = f"MCP工具调用异常: {str(e)}"
            logger.error(error_msg, exc_info=True)
            return f"❌ 调用失败: {error_msg}"

    @classmethod
    async def get_mcp_client_tools(cls, server_name: Optional[str] = None) -> List[Dict[str, Any]]:
        """获取MCP客户端中的工具列表"""
        try:
            tools = await mcp_client.get_tools(server_name)

            # 转换为字典格式
            tool_list = []
            for tool in tools:
                tool_dict = {
                    "name": tool.name,
                    "description": tool.description,
                    "server_name": tool.server_name,
                    "input_schema": tool.input_schema
                }
                tool_list.append(tool_dict)

            logger.info(f"📋 获取到 {len(tool_list)} 个MCP客户端工具")
            return tool_list

        except Exception as e:
            logger.error(f"❌ 获取MCP客户端工具失败: {str(e)}")
            return []

    @classmethod
    def get_mcp_client_status(cls) -> Dict[str, Any]:
        """获取MCP客户端状态"""
        try:
            connected_servers = mcp_client.get_connected_servers()

            status = {
                "connected": len(connected_servers) > 0,
                "connected_servers": connected_servers,
                "server_count": len(connected_servers),
                "available_tools_count": len(mcp_client.available_tools)
            }

            logger.info(f"📊 MCP客户端状态: {status}")
            return status

        except Exception as e:
            logger.error(f"❌ 获取MCP客户端状态失败: {str(e)}")
            return {
                "connected": False,
                "error": str(e),
                "connected_servers": [],
                "server_count": 0,
                "available_tools_count": 0
            }


# 全局MCP工厂实例
mcp_factory = MCPFactory()
